package cn.birdbaby.plugins.sync;

import cn.birdbaby.plugins.sync.fieldsyncer.AbstractFieldSyncer;
import cn.birdbaby.plugins.sync.support.ISyncer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author llorando 12/8/24 1:05 pm
 */
public abstract class AbstractSyncer implements ISyncer {
    private static final Logger LOG = Logger.getInstance(AbstractSyncer.class);

    public abstract void sync(PsiClass psiClass);

    public abstract String getElementName(PsiElement element);

    public PsiClass findClass(PsiClass psiClass) {
        //fixme 根据注解提供的路径+类名，找到需处理的类
        String name = getPrefix()+psiClass.getName() + getSuffix();
        PsiClass result= JavaPsiFacade.getInstance(psiClass.getProject()).findClass(name, GlobalSearchScope.allScope(psiClass.getProject()));
        if(result==null){
            LOG.debug("找不到"+name);
        }
        return result;
    }

    public Map<String, PsiElement> trans2Map(List<PsiElement> elements) {
        Map<String, PsiElement> psiElementHashMap = new HashMap<>();
        for (PsiElement element : elements) {
            psiElementHashMap.put(getElementName(element), element);
        }
        return psiElementHashMap;
    }

    /**
     * 比对source和target之间的元素差异，过滤出source中存在，而target中不存在的元素
     * @param source
     * @param target
     * @return
     */
    public List<PsiElement> filterPsiElement(List<PsiElement> source, List<PsiElement> target) {
        List<PsiElement> result = new ArrayList<>();
        Map<String, PsiElement> map = trans2Map(target);
        for (PsiElement method : source) {
            if (skip(method)) continue;
            String name = getElementName(method);
            if (!map.containsKey(name)) {
                result.add(method);
            }
        }
        return result;
    }

    public abstract boolean skip(PsiElement element);

    //获取后缀名，同时也作为spi注册时的名称
    public String getSuffix(){
        return "";
    }
    public String getPrefix(){
        return "";
    }

    public void addPsiElement(PsiClass destination, List<PsiElement> psiElements) {
        PsiJavaToken rbrace = locateRBrace(destination);//最后一个，一定是右大括号
        for (PsiElement element : psiElements) {
            destination.addBefore(element.copy(),rbrace);
        }
    }

    public PsiJavaToken locateRBrace(PsiClass psiClass) {
        List<PsiJavaToken> javaTokens = PsiTreeUtil.findChildrenOfAnyType(psiClass, PsiJavaToken.class).stream().collect(Collectors.toList());
        PsiJavaToken rbrace = javaTokens.get(javaTokens.size() - 1);//最后一个，一定是右大括号
        return rbrace;
    }
}
